package com.cls.business.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cls.business.entity.DeclareTopic;
import com.cls.business.entity.Notice;
import com.cls.business.entity.TopicPlan;
import com.cls.business.mapper.DeclareTopicMapper;
import com.cls.business.mapper.NoticeMapper;
import com.cls.business.mapper.TopicPlanMapper;
import com.cls.business.service.IMessageService;
import com.cls.business.service.INoticeService;
import com.cls.business.service.ITopicPlanService;
import com.cls.business.vo.NoticePageVO;
import com.cls.common.entity.QueryRequest;
import com.cls.common.enums.DictEnum;
import com.cls.common.enums.EmailTextEnum;
import com.cls.common.exception.MyException;
import com.cls.common.utils.EmailSenderUtil;
import com.cls.system.entity.Configure;
import com.cls.system.entity.User;
import com.cls.system.service.IConfigureService;
import com.cls.system.service.IUserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 通知公告 Service实现
 *
 * @author weimaomao
 * @date 2020-11-10 09:36:03
 */
@Service
@RequiredArgsConstructor
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements INoticeService {

    private final TopicPlanMapper topicPlanMapper;
    private final DeclareTopicMapper declareTopicMapper;
    private final IConfigureService configureService;
    private final IMessageService messageService;
    private final EmailSenderUtil emailSenderUtil;
    private final IUserService userService;
    private final ITopicPlanService topicPlanService;

    @Override
    public PageInfo<Notice> findNotices(QueryRequest request, Notice notice) {
        LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(notice.getTitle())) {
            queryWrapper.like(Notice::getTitle, notice.getTitle());
        }
        if (StringUtils.isNotEmpty(notice.getTypeCode())) {
            queryWrapper.eq(Notice::getTypeCode, notice.getTypeCode());
        }
        if (null != notice.getIsPublish()) {
            queryWrapper.eq(Notice::getIsPublish, true);
        }
        queryWrapper.orderByAsc(Notice::getIsPublish);
        queryWrapper.orderByDesc(Notice::getPublishTime);
        // TODO 设置查询条件
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<Notice> list = this.list(queryWrapper);
        PageInfo pageInfo = new PageInfo(list);
        return pageInfo;
    }

    @Override
    public PageInfo<Notice> findNotices(QueryRequest request, LambdaQueryWrapper<Notice> queryWrapper) {
        // TODO 设置查询条件
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<Notice> list = this.list(queryWrapper);
        PageInfo pageInfo = new PageInfo(list);
        return pageInfo;
    }

    @Override
    public List<Notice> findNotices(Notice notice) {
        LambdaQueryWrapper<Notice> queryWrapper = new LambdaQueryWrapper<>();
        if (StringUtils.isNotEmpty(notice.getTypeCode())) {
            queryWrapper.eq(Notice::getTypeCode, notice.getTypeCode());
        }
        // TODO 设置查询条件
        return this.baseMapper.selectList(queryWrapper);
    }

    @Override
    public List<Notice> findNotices(LambdaQueryWrapper<Notice> queryWrapper) {
        return this.list(queryWrapper);
    }

    /**
     * 查询课题征集的有效期的通知公告
     *
     * @return
     */
    @Override
    public List<Notice> findKTZJValidNotices() {

        // TODO 设置查询条件
        return this.baseMapper.findKtZJValidNotices(DictEnum.NOTICE_TYPE_KTZJ.getCode());
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateNotice(Notice notice) {
        //当选择的通知公告类型为课题征集时，要创建课题计划
        if (DictEnum.NOTICE_TYPE_KTZJ.getCode().equals(notice.getTypeCode())) {
            TopicPlan topicPlan = topicPlanMapper.selectBySelectNoticeId(notice.getNoticeId());
            topicPlan.setSelectBeginTime(notice.getSelectBeginTime());
            topicPlan.setSelectEndTime(notice.getSelectEndTime());
            topicPlanMapper.updateById(topicPlan);
        }//如果是课题指南时 需要更新一下计划的申请的通知公告id和时间们
        else if (DictEnum.NOTICE_TYPE_KTZN.getCode().equals(notice.getTypeCode())) {
            //根据年份获取计划
            TopicPlan topicPlan = topicPlanMapper.selectByApplyNoticeId(notice.getNoticeId());
            Configure configure = configureService.getById(topicPlan.getConfigureId());
            String businessTypeCode = configure.getBusinessTypeCode();
            //有意向则必须填写意向表申请时间
            boolean isIntention = DictEnum.CONFIGURE_INTENTION.getCode().equals(businessTypeCode);
            if (isIntention && notice.getIntentionSubmitEndTime() == null) {
                throw new MyException("对不起，意向表提交结束时间不能为空！");
            }
            topicPlan.setApplySubmitEndTime(notice.getApplySubmitEndTime());
            topicPlan.setSubmitBeginTime(notice.getSubmitBeginTime());
            topicPlan.setIntentionSubmitEndTime(notice.getIntentionSubmitEndTime());
            topicPlanMapper.updateById(topicPlan);
        }//如果是结项通知时 需要更新一下计划的时间们
        else if (DictEnum.NOTICE_TYPE_JXGG.getCode().equals(notice.getTypeCode())) {
            TopicPlan topicPlan = topicPlanMapper.selectByConcludeNoticeId(notice.getNoticeId());
            topicPlan.setSelectBeginTime(notice.getSelectBeginTime());
            topicPlan.setSelectEndTime(notice.getSelectEndTime());
            topicPlanMapper.updateById(topicPlan);
        }//如果是结项通知时 需要更新一下计划的时间们
        else if (DictEnum.NOTICE_TYPE_NLXGG.getCode().equals(notice.getTypeCode())) {
            TopicPlan topicPlan = topicPlanMapper.selectByPreItemNoticeId(notice.getNoticeId());
            topicPlan.setPreItemBeginTime(notice.getPreItemBeginTime());
            topicPlan.setPreItemEndTime(notice.getPreItemEndTime());
            topicPlanMapper.updateById(topicPlan);
        }

        this.updateById(notice);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNotice(Notice notice) {
        LambdaQueryWrapper<Notice> wrapper = new LambdaQueryWrapper<>();
        // TODO 设置删除条件
        this.remove(wrapper);
    }

    /**
     * 删除
     *
     * @param ids
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteNotices(String[] ids) {
        List<String> list = Arrays.asList(ids);
        // 删除专家
        boolean b = this.removeByIds(list);
        System.out.println(b);
    }

    /**
     * 更新发布状态
     *
     * @param noticeId
     * @param isPublish
     */
    @Override
    public void updateNoticePublish(Long noticeId, Boolean isPublish) {
        Notice notice = this.baseMapper.selectById(noticeId);
        Date oldPublishTime = notice.getPublishTime();
        //如果当前是发布的数据，并且oldpublishTime之前没有设置过值
        if (isPublish && oldPublishTime==null) {
            notice.setPublishTime(new Date());
        }
        notice.setIsPublish(isPublish);
        this.baseMapper.updateById(notice);
        //判断是否第一次发布且是结项结果发布，更新所有第一次没通过的课题的最晚申请更新时间
        if (!isPublish || oldPublishTime != null) {
            return;
        }
        if (DictEnum.NOTICE_TYPE_RESULT_JXGG.getCode().equals(notice.getTypeCode())) {
            //结项结果通过公告id查询计划
            TopicPlan topicPlan = topicPlanMapper.selectByConcludeFinishNoticeId(noticeId);
            //获取所有的第一次未通过课题们
            List<DeclareTopic> declareTopicList = declareTopicMapper.selectFirstNoPass(topicPlan.getPeriod());
            //设置最晚申请更新时间
            declareTopicList.forEach(item -> {
                //当前时间添加六个月
                Calendar calendar = Calendar.getInstance();
                calendar.setTime(new Date());
                calendar.add(Calendar.MONTH, 6);
                item.setLatestApplyTime(calendar.getTime());
                declareTopicMapper.updateById(item);
            });
        } else if (DictEnum.NOTICE_TYPE_NLXGG.getCode().equals(notice.getTypeCode())) {
            //发布公告：您申报的课题定级为重大课题/重点课题/…，并已拟立项，请登录系统填报拟立项申请书。 定级完毕的数据进行发布通知
            //拟立项公告发出之后，把所有的已评审状态的年度课题改成拟立项失败
            String year = notice.getYear();
            //根据年份查询年度课题
            TopicPlan topicPlan = topicPlanService.selectAnnualByYear(year);
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            List<DeclareTopic> preItemTopic = declareTopicMapper.findAnnualDeclareTopicByPlanIdAndStatusTypeCode(topicPlan.getPlanId(), DictEnum.PRE_ITEM.getCode(),DictEnum.ANNUAL.getCode());
            preItemTopic.forEach(item -> {
                //发送系统消息
                String format = String.format(EmailTextEnum.CLASS_RATING_TEXT.getText(), item.getName(), item.getFinalLevelTypeVal());
                messageService.sendMessageById(format, user, item.getUserId());
                //发送邮件
                User receiveUser = userService.getById(item.getUserId());
                emailSenderUtil.sendEmail(EmailTextEnum.CLASS_RATING.getText(), format, receiveUser.getEmail());
            });
        }else if(DictEnum.NOTICE_TYPE_RESULT_JXGG.getCode().equals(notice.getTypeCode())){
            //发布公告：您申报的课题定级为重大课题/重点课题/…，并已拟立项，请登录系统填报拟立项申请书。 定级完毕的数据进行发布通知
            //拟立项公告发出之后，把所有的已评审状态的年度课题改成拟立项失败
            String year = notice.getYear();
            //根据年份查询年度课题
            TopicPlan topicPlan = topicPlanService.selectAnnualByYear(year);
            User user = (User) SecurityUtils.getSubject().getPrincipal();
            //获取此期次中所有的申请课题进行发布通知
            List<DeclareTopic> declareTopicList = declareTopicMapper.findFinalLevelTypeAndUserIdByPlanId(topicPlan.getPlanId());
            declareTopicList.forEach(item->{
                //发送邮件
                User receiveUser = userService.getById(item.getUserId());
                String message = String.format(EmailTextEnum.PRE_ITEM_TEXT.getText(), item.getName(), item.getFinalLevelType());
                messageService.sendMessageById(message, user, item.getUserId());
                emailSenderUtil.sendEmail(EmailTextEnum.PRE_ITEM.getText(),message,receiveUser.getEmail());
            });
        }else if(DictEnum.NOTICE_TYPE_KTZN.getCode().equals(notice.getTypeCode())){
            String year = notice.getYear();
            TopicPlan topicPlan = topicPlanService.selectByPeriod(year);
            topicPlan.setApplyNoticeId(notice.getNoticeId());
            topicPlanService.updateById(topicPlan);
        }

    }


    /**
     * 获取当前、上一条、下一条通知公告
     *
     * @return
     */
    @Override
    public NoticePageVO getOneHaveNextLast(Long noticeId) {
        NoticePageVO noticePageVO = new NoticePageVO();
        Notice notice = this.baseMapper.selectById(noticeId);
        noticePageVO.setNotice(notice);
        Notice preNotice = this.baseMapper.getPreNotice(notice.getNoticeId(), notice.getModifyTime());
        noticePageVO.setPreNotice(preNotice);
        Notice nextNotice = this.baseMapper.getNextNotice(notice.getNoticeId(), notice.getModifyTime());
        noticePageVO.setNetxNotice(nextNotice);
        return noticePageVO;
    }
}
